{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "6125a85e",
   "metadata": {},
   "source": [
    "# Microsoft OneNote\n",
    "\n",
    "This notebook covers how to load documents from `OneNote`.\n",
    "\n",
    "## Prerequisites\n",
    "1. Register an application with the [Microsoft identity platform](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app) instructions.\n",
    "2. When registration finishes, the Azure portal displays the app registration's Overview pane. You see the Application (client) ID. Also called the `client ID`, this value uniquely identifies your application in the Microsoft identity platform.\n",
    "3. During the steps you will be following at **item 1**, you can set the redirect URI as `http://localhost:8000/callback`\n",
    "4. During the steps you will be following at **item 1**, generate a new password (`client_secret`) under Application Secrets section.\n",
    "5. Follow the instructions at this [document](https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-expose-web-apis#add-a-scope) to add the following `SCOPES` (`Notes.Read`) to your application.\n",
    "6. You need to install the msal and bs4 packages using the commands `pip install msal` and `pip install beautifulsoup4`.\n",
    "7. At the end of the steps you must have the following values: \n",
    "- `CLIENT_ID`\n",
    "- `CLIENT_SECRET`\n",
    "\n",
    "## 🧑 Instructions for ingesting your documents from OneNote\n",
    "\n",
    "### 🔑 Authentication\n",
    "\n",
    "By default, the `OneNoteLoader` expects that the values of `CLIENT_ID` and `CLIENT_SECRET` must be stored as environment variables named `MS_GRAPH_CLIENT_ID` and `MS_GRAPH_CLIENT_SECRET` respectively. You could pass those environment variables through a `.env` file at the root of your application or using the following command in your script.\n",
    "\n",
    "```python\n",
    "os.environ['MS_GRAPH_CLIENT_ID'] = \"YOUR CLIENT ID\"\n",
    "os.environ['MS_GRAPH_CLIENT_SECRET'] = \"YOUR CLIENT SECRET\"\n",
    "```\n",
    "\n",
    "This loader uses an authentication called [*on behalf of a user*](https://learn.microsoft.com/en-us/graph/auth-v2-user?context=graph%2Fapi%2F1.0&view=graph-rest-1.0). It is a 2 step authentication with user consent. When you instantiate the loader, it will call will print a url that the user must visit to give consent to the app on the required permissions. The user must then visit this url and give consent to the application. Then the user must copy the resulting page url and paste it back on the console. The method will then return True if the login attempt was successful.\n",
    "\n",
    "\n",
    "```python\n",
    "from langchain_community.document_loaders.onenote import OneNoteLoader\n",
    "\n",
    "loader = OneNoteLoader(notebook_name=\"NOTEBOOK NAME\", section_name=\"SECTION NAME\", page_title=\"PAGE TITLE\")\n",
    "```\n",
    "\n",
    "Once the authentication has been done, the loader will store a token (`onenote_graph_token.txt`) at `~/.credentials/` folder. This token could be used later to authenticate without the copy/paste steps explained earlier. To use this token for authentication, you need to change the `auth_with_token` parameter to True in the instantiation of the loader.\n",
    "\n",
    "```python\n",
    "from langchain_community.document_loaders.onenote import OneNoteLoader\n",
    "\n",
    "loader = OneNoteLoader(notebook_name=\"NOTEBOOK NAME\", section_name=\"SECTION NAME\", page_title=\"PAGE TITLE\", auth_with_token=True)\n",
    "```\n",
    "\n",
    "Alternatively, you can also pass the token directly to the loader. This is useful when you want to authenticate with a token that was generated by another application. For instance, you can use the [Microsoft Graph Explorer](https://developer.microsoft.com/en-us/graph/graph-explorer) to generate a token and then pass it to the loader.\n",
    "\n",
    "```python\n",
    "from langchain_community.document_loaders.onenote import OneNoteLoader\n",
    "\n",
    "loader = OneNoteLoader(notebook_name=\"NOTEBOOK NAME\", section_name=\"SECTION NAME\", page_title=\"PAGE TITLE\", access_token=\"TOKEN\")\n",
    "```\n",
    "\n",
    "### 🗂️ Documents loader\n",
    "\n",
    "#### 📑 Loading pages from a OneNote Notebook\n",
    "\n",
    "`OneNoteLoader` can load pages from OneNote notebooks stored in OneDrive. You can specify any combination of `notebook_name`, `section_name`, `page_title` to filter for pages under a specific notebook, under a specific section, or with a specific title respectively. For instance, you want to load all pages that are stored under a section called `Recipes` within any of your notebooks OneDrive.\n",
    "\n",
    "\n",
    "```python\n",
    "from langchain_community.document_loaders.onenote import OneNoteLoader\n",
    "\n",
    "loader = OneNoteLoader(section_name=\"Recipes\", auth_with_token=True)\n",
    "documents = loader.load()\n",
    "```\n",
    "\n",
    "#### 📑 Loading pages from a list of Page IDs\n",
    "\n",
    "Another possibility is to provide a list of `object_ids` for each page you want to load. For that, you will need to query the [Microsoft Graph API](https://developer.microsoft.com/en-us/graph/graph-explorer) to find all the documents ID that you are interested in. This [link](https://learn.microsoft.com/en-us/graph/onenote-get-content#page-collection) provides a list of endpoints that will be helpful to retrieve the documents ID.\n",
    "\n",
    "For instance, to retrieve information about all pages that are stored in your notebooks, you need make a request to: `https://graph.microsoft.com/v1.0/me/onenote/pages`. Once you have the list of IDs that you are interested in, then you can instantiate the loader with the following parameters.\n",
    "\n",
    "\n",
    "```python\n",
    "from langchain_community.document_loaders.onenote import OneNoteLoader\n",
    "\n",
    "loader = OneNoteLoader(object_ids=[\"ID_1\", \"ID_2\"], auth_with_token=True)\n",
    "documents = loader.load()\n",
    "```\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bb36fe41",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
